﻿using Dapper;
using Dapper.Contrib.Extensions;
using SimulationCenter.Data;
using System;
using System.Threading.Tasks;

namespace SimulationCenter.Tasks.Svrs
{
    public class SubscriptionSvr : ISubscriptionSvr
    {
        private readonly SqlProvider _sqlProvider;

        public SubscriptionSvr(SqlProvider sqlProvider)
        {
            _sqlProvider = sqlProvider;
        }

        public async Task BindDeviceSubscription(string device, string subscription)
        {
            var sql = "SELECT * FROM ScDeviceSubscription WHERE SERIAL = @device AND SUBSCRIPTION = @subscription LIMIT 1";
            var param = new { device, subscription };

            ScDeviceSubscription deviceSubscription = null;
            _sqlProvider.Executing(conn =>
            {
                deviceSubscription = conn.QueryFirstOrDefault<ScDeviceSubscription>(sql, param);
            });

            if (deviceSubscription == null)
            {
                _sqlProvider.Executing(conn =>
                {
                    conn.Insert(new ScDeviceSubscription
                    {
                        Serial = device,
                        Subscription = subscription,
                        UpdateAt = DateTime.Now
                    });
                });
            }

            await Task.CompletedTask;
        }

        public void BindSubscription(string id, string subscription)
        {
            if (FindSubscription(id) != null)
                return;

            _sqlProvider.Executing(conn => 
            {
                conn.Insert(new ScSubscription() { Id = id, Subscription = subscription });
            });
        }

        public ScSubscription FindSubscription(string idOrSubscriptin)
        {
            var sql = "SELECT * FROM ScSubscription WHERE Id = @id OR Subscription = @subscription";
            var param = new { id = idOrSubscriptin, subscription = idOrSubscriptin };

            ScSubscription subscription = null;
            _sqlProvider.Executing(conn => 
            {
                subscription = conn.QueryFirstOrDefault<ScSubscription>(sql, param);
            });

            return subscription;
        }

        public async Task<(ScMsgRange range, int? lastDays)> GetFetchMsgsRange(string subscription)
        {
            var sql = "SELECT * FROM ScDeviceTask WHERE SUBSCRIPTION = @subscription AND STATUS = 5 ORDER BY StartAt DESC LIMIT 1";
            var param = new {subscription};

            ScDeviceTask deviceTask = null;
            _sqlProvider.Executing(conn =>
            {
                deviceTask = conn.QueryFirstOrDefault<ScDeviceTask>(sql, param);
            });

            if (deviceTask == null)
                throw new Exception($"There are no devices task target with '{subscription}'");

            ScTask scTask = null;

            _sqlProvider.Executing(conn => 
            {
                scTask = conn.Get<ScTask>(deviceTask.ScTaskId);
            });

            if (scTask == null)
                throw new Exception($"Cannot found ScTask which id is {deviceTask.ScTaskId}");

            await Task.CompletedTask;

            return (scTask.MsgRange, scTask.LastDays);
        }
    }
}
